import React, { FC, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { Button, Dropdown, Menu, message, Popconfirm } from 'antd';
import { getMessage, TextWidget } from '@inbiz/react';
import '../../style.less';
import { ActionProps, ActionsProps } from '../../interfaces';
import { InbizIcon } from '@inbiz/utils';
import cls from 'classnames';
import { EllipsisOutlined } from '@ant-design/icons';
import { InBizTableRefCtx, TableCtx } from '../../context';
import { ActionEnum, arrIsEmpty, EventsMap } from '../../shared';
import { useColumnConfig, useIsDesigner } from '../../hooks';
import { AuthButton, hasAuth } from '@inbiz/basic/AuthForm';

const formatterIntl = (ele?: string) => {
  if (ele) {
    return <TextWidget>{ele}</TextWidget>;
  }
  return ele;
};
const renderButton = (
  tableHeaderType: string = 'text',
  inLineType: string = 'text',
  position: string = 'tableHeader',
  text: string,
  icon?: { type: string; color: string },
) => {
  const renderMap = {
    text: () => formatterIntl(text),
    icon: () =>
      icon ? <InbizIcon type={icon?.type} style={{ color: icon?.color }} /> : formatterIntl(text),
    iconText: () => (
      <>
        {icon && <InbizIcon type={icon?.type} style={{ color: icon?.color }} />}
        {formatterIntl(text)}
      </>
    ),
  };
  if (position === 'tableHeader') {
    return renderMap[tableHeaderType]();
  }
  return renderMap[inLineType]();
};

const Action = React.memo((props: ActionProps) => {
  const { buttonType, className, position, ...other } = props;
  const { formItems } = useColumnConfig();
  const title = renderButton(
    formItems.tableHeaderBtnShow,
    formItems.inLineBtnShow,
    position,
    props.actionName,
    props.icon,
  );
  const { state, dispatch, emit, tableCacheRef } = useContext(TableCtx);
  const { eventsRef } = useContext(InBizTableRefCtx);

  const isDesignable = useIsDesigner();
  const [loading, setLoading] = useState(false);
  const needPage = [ActionEnum.add, ActionEnum.edit, ActionEnum.view];
  const opsListen = [ActionEnum.add, ActionEnum.edit,ActionEnum.del]
  const onClick = useCallback(
    async (e) => {
      document.body.click();
      const nope = () =>
        new Promise((resolve) => {
          setTimeout(() => {
            resolve(undefined);
          }, 0);
        });
      await nope();
      e.stopPropagation();
      if (opsListen.includes(props.actionType)) {
        const result =
          (await eventsRef?.current.onBeforeOperationAsync?.(props.actionType, props?.data)) ??
          true;
        if (!result) {
          return;
        }
      }
      if (props.actionType !== ActionEnum.del) {
        (emit as any)?.(EventsMap.onClick, props.actionType, props);
      }
      if (isDesignable || props.actionType === ActionEnum.custom) {
        return;
      }
      if (needPage.includes(props.actionType) && !(props.page as ActionEnum)) {
        message.warning(getMessage('SubTable.message.pageRequired'));
        return;
      }
      if (props.actionType !== ActionEnum.add) {
        setLoading(true);
      }
      await dispatch?.({ ...props });
      if (props.actionType === ActionEnum.del) {
        tableCacheRef.current.setSelect([]);
      }
    },
    [props.actionType],
  );

  useEffect(() => {
    if (state) {
      state.finally(() => setLoading(false));
    }
  }, [state]);

  const actionMap = {
    del: (() => {
      return (
        <Popconfirm
          title={getMessage('SubTable.makeSureDelte')}
          placement="bottom"
          onConfirm={onClick}
          disabled={other?.disabled}
          overlayStyle={{minWidth:150}}
          onCancel={e => e?.stopPropagation()}
        >
          <Button
            operationflag={props.operationflag}
            className={className}
            type={buttonType}
            disabled={other?.disabled}
            onClick={async (e) => {
              e.stopPropagation();
              (emit as any)?.(EventsMap.onClick, props.actionType, props);
              if (props.actionType !== ActionEnum.del) {
                const result =
                  (await eventsRef?.current.onBeforeOperationAsync?.(
                    props.actionType,
                    props?.data,
                  )) ?? true;
                if (!result) {
                  return;
                }
              }

              if (!props.data?.id && arrIsEmpty(tableCacheRef.current.keyList)) {
                message.warning(getMessage('SubTable.message.deleteChoosed'));
                return;
              }
            }}
          >
            {formatterIntl(title)}
          </Button>
        </Popconfirm>
      );
    })(),
  };

  const Comp = useMemo(() => actionMap[props.actionType], [props.actionType]);
  return Comp ? (
    Comp
  ) : (
    <>
      <Button
        className={className}
        disabled={loading || other?.disabled}
        operationflag={props.operationflag}
        type={buttonType}
        onClick={onClick}
      >
        {formatterIntl(title)}
      </Button>
    </>
  );
});
Action.displayName = 'Action';
export const DropDownActions: React.FC<ActionsProps> = (props) => {
  const { className, actions, ...other } = props;
  return (
    <Dropdown
      overlayClassName={'subTable-dropdown-overlay-menu'}
      overlay={
        <Menu>
          {actions?.map((action) => {
            return (
              <Menu.Item key={action.id}>
                <Action {...other} {...action} data={props.data} buttonType={'text'} />
              </Menu.Item>
            );
          })}
        </Menu>
      }
    >
      {props.children}
    </Dropdown>
  );
};

const Actions: FC<ActionsProps> = (props) => {
  const { auth, inbiz } = useColumnConfig();
  const { className, actions, displayQty = 3, ...other } = props;
  const leftActions = actions?.slice(displayQty)?.map((ele) => {
    return {
      ...ele,
      ...hasAuth(
        {
          table: [{ ...ele, operationType: ele.actionType }],
          auth: auth,
        },
        ele.actionType,
        inbiz?.auth,
      ),
    };
  });
  const leftAuthActions = leftActions?.filter((ele) => ele.auth);
  return (
    <div className={cls('inbiz-subtable-actions', className)}>
      {actions?.slice(0, displayQty).map((action, index) => {
        const { render, ...rest } = action;
        if (render) {
          return render?.('action-item');
        }

        return (
          <AuthButton
            key={`${action.actionType}_${action.actionName}_${index}`}
            auth={auth}
            operation={[{ ...action, operationType: action.actionType }]}
            type={action.actionType}
            authList={inbiz?.auth}
          >
            <Action
              key={action.id}
              {...other}
              {...rest}
              data={props.data}
              className={'action-item'}
            />
          </AuthButton>
        );
      })}
      {(actions?.length || 0) > displayQty && leftAuthActions && leftAuthActions.length > 0 && (
        <DropDownActions {...props} actions={leftAuthActions}>
          <Button icon={<EllipsisOutlined />} style={{ width: 38 }} />
        </DropDownActions>
      )}
    </div>
  );
};

export default React.memo(Actions);
